<?php


namespace app\cms\community\lib;

use app\cms\model\buildModel;
use app\cms\model\formFieldModel;
use app\cms\model\formModel;
use iflow\Response;
use think\db\exception\DataNotFoundException;
use think\db\exception\DbException;
use think\db\exception\ModelNotFoundException;
use think\facade\Db;
use think\Model;

/**
 * 自定义表单模型数据
 * Class modelData
 * @package app\cms\community\lib
 */
class modelData
{

    /**
     * @var object|null|Model
     */
    protected object|null $query = null;

    // 查询条件
    protected array $where = [];

    protected array $whereLike = [];

    // 查询目标表单模型
    protected array $formModel = [];
    // 查询目标表单模型字段
    protected ?array $formField = [];

    // 关联查询
    protected array $condition = [];

    // 查询字段
    private array $fields = [
        'admin_user_table.avatar',
        'admin_user_table.user_name',
        'admin_user_table.uid',
        'admin_user_table.signature'
    ];

    // 表单id
    protected int $form_id;
    // 类目id
    protected string|int $groupId = "";
    // 数据id
    protected string|int $id = "";
    // 创建人id
    protected string|int $user_id = "";
    // 拓展数据
    protected array $options = [
        'order' => 'desc',
        'pageSize' => 15,
        'keyword' => ''
    ];
    // 统计总数
    protected int $count = 0;

    /**
     * 执行查询
     * @return Response
     */
    public function query(): Response {
        if ($this->query === null) {
            $buildModel = new buildModel(table: $this->formModel['form_name']);
            $this->query = Db::connect($buildModel -> getConnection());
        }
        $this->query = $this->query -> name($this->formModel['form_name']);

        $this->query -> where($this->where);
        $this->setFormField();
        if (isset($this->options['keyword']) && $this->options['keyword'] !== '') {
            $this->setWhereLike("{$this->formModel['form_name']}.{$this->formModel['title_field']}", $this->options['keyword']);
        }

        // 模糊查询
        foreach ($this->whereLike as $like) {
            $this->query -> whereLike($like[0], $like[1]);
        }

        // 连表查询
        foreach ($this->condition as $name => $cond) {
            $this->query -> leftJoin($name, $cond);
        }

        $this->query
            -> field($this->fields)
            -> withAttr('create_time', function ($value, $data) {
                return date('Y-m-d H:i:s', $value);
            })
            -> order([
                $this->formModel['form_name'] .".create_time" => $this->options['order']
            ]);

        if ($this->options['offset']) {
            return $this->offsetFind();
        }

        if ($this->id) {
            return $this->find();
        }
        return $this->paginate();
    }


    /**
     * @return Response
     * @throws DataNotFoundException
     * @throws DbException
     * @throws ModelNotFoundException
     */
    private function offsetFind(): Response {
        $list = $this->query -> limit(
            $this->options['offset'],
            $this->options['limit'] ?? 1
        ) -> select();

        if (!$list) return message() -> nodata('暂无数据');
        return message() -> success('查询成功', $list);
    }

    /**
     * 查询单条记录
     * @return Response
     */
    private function find(): Response
    {
        $data = $this->query -> where($this->formModel['form_name']. '.id', $this->id) -> find();
        if ($data) {
            $data['form_id'] = $this->form_id;
            $data['title_field'] = $this->formModel['title_field'];
            return message() -> success('查询成功', $data);
        }
        return message() -> nodata('暂无数据');
    }

    /**
     * 分页查询
     * @return Response
     */
    private function paginate(): Response
    {
        $query = $this->query -> paginate([
            'list_rows' => $this->options['pageSize'],
            'page' => request() -> getParams('page')
        ]);

        $items = $query -> items();
        return $items ?
            message() -> success('查询成功', $items, [
                'count' => $query -> total(),
                'page' => $query -> lastPage(),
                'form_id' => $this->form_id,
                'title_field' => $this->formModel['title_field']
            ]): message() -> nodata('暂无数据');
    }

    /**
     * 设置 查询数据字段
     */
    protected function setFormField()
    {

        $fieldModel = new formFieldModel;
        $this->formField = $fieldModel -> getFields($this->form_id) -> data['items'];
        foreach ($this->formField as $field) {
            $this->fields[] = sprintf(
                "%s.%s",
                $this->formModel['form_name'],
                $field['form_field_name']
            );
        }

        // 查询绑定模型列
        if ($this->formModel['form_bind_model'] !== '-1') {
            $this->condition[$this->formModel['form_bind_model']] = sprintf(
                "%s.uuid = %s.foreign_uuid",
                $this->formModel['form_bind_model'],
                $this->formModel['form_name']
            );

            // 绑定模型字段
            $bindFormField = $fieldModel -> getFieldByFormName(
                $this->formModel['form_bind_model']) -> data['items'];

            foreach ($bindFormField as $key => $bf) {
                 $this->fields[] = "{$this->formModel['form_bind_model']}.{$bf['form_field_name']} as bind_model_". $bf['form_field_name'];
            }
        }
    }

    /**
     * @param int $form_id
     * @return static
     * @throws \Exception
     */
    public function setFormId(int $form_id): static
    {
        $this->form_id = $form_id;
        $this->formModel = (new formModel) -> getForm($this->form_id) ?: [];
        $this->formModel ?
            $this->condition['admin_user_table'] = 'admin_user_table.uid = '.$this -> formModel['form_name']. '.create_by':
            throw new \Exception('表单模型不存在');
        return $this;
    }

    /**
     * @param string|int $groupId
     * @return static
     */
    public function setGroupId(string|int $groupId): static
    {
        if ($groupId) {
            $this->groupId = $groupId;
            $this->where["{$this -> formModel['form_name']}.foreign_uuid"] = $groupId;
        }
        return $this;
    }

    /**
     * @param string|int $id
     * @return static
     */
    public function setId(string|int $id): static
    {
        if ($id) {
            $this->id = $id;
            $this->where["{$this -> formModel['form_name']}.id"] = $id;
        }
        return $this;
    }

    /**
     * @param array $options
     * @return static
     */
    public function setOptions(array $options): static
    {
        $this->options = array_merge($this->options, $options);
        return $this;
    }

    /**
     * 设置创建者 UID
     * @param int|string $user_id
     * @return static
     */
    public function setUserId(int|string $user_id): static
    {
        if ($user_id) {
            $this->user_id = $user_id;
            $this->where['admin_user_table.uid'] = $user_id;
        }
        return $this;
    }

    /**
     * 搜索条件
     * @param array $where
     * @return static
     */
    public function setWhere(array $where): static
    {
        $this->where = array_merge($this->where, $where);
        return $this;
    }

    /**
     * 模糊搜索
     * @param string $field | 字段名称 tableName. Field
     * @param string $condition
     * @return static
     */
    public function setWhereLike(string $field, string $condition): static {
        $this->whereLike[] = [$field, "%{$condition}%"];
        return $this;
    }

    /**
     * 指定模型字段自增
     * @param string $field
     * @param string $uuid
     * @param int $number
     * @param string $type
     * @return bool|string
     */
    public function modelFieldIncOrDec(string $field, string $uuid, int $number, string $type): bool|string
    {
        $model = (new formModel) -> getForm($this -> form_id);
        if ($model === null) return '请选择需要更新的模型';
        (new buildModel(table: $model['form_name']))
            -> where([
                'uuid' => $uuid
            ]) -> {$type}($field, $number);
        return true;
    }
}